package clock.socoolby.com.clock.widget.animatorview.animator;


import android.graphics.Canvas;
import android.graphics.Paint;

import java.util.ArrayList;
import java.util.List;

import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry;

//参考自:https://github.com/zhuwentao2150/RippleView
public class RippleAnimator extends AbstractAnimator<RippleAnimator.Ripple> {


    public RippleAnimator() {
        super(DYNAMIC_QUANTITY);
    }

    @Override
    public void reset() {
        super.reset();
        list.add(createNewEntry());
    }

    @Override
    public Ripple createNewEntry() {
        Style style;
        int ran=rand.nextInt(3);
        if(ran==2)
            style=Style.OUT;
        else if(ran==1)
            style=Style.BREATH;
        else
            style=Style.IN;
        return new Ripple(width,height,color,style);
    }

    @Override
    protected void initPaint(Paint mPaint) {
        super.initPaint(mPaint);

    }

    public enum Style{
        IN,OUT,BREATH;
    }

    public class Ripple implements I_AnimatorEntry {
        // 画笔对象
        private Paint mPaint;

        // View宽
        private float mWidth;

        // View高
        private float mHeight;

        // 声波的圆圈集合
        private List<Circle> mRipples;

        private int sqrtNumber;

        // 圆圈扩散的速度
        private int mSpeed;

        // 圆圈之间的密度
        private int mDensity;

        // 圆圈的颜色
        private int mColor;

        // 圆圈是否为填充模式
        private boolean mIsFill;

        // 圆圈是否为渐变模式
        private boolean mIsAlpha;

        Style style;


        public Ripple(float mWidth, float mHeight, int mColor,Style style) {
            this.mWidth = mWidth;
            this.mHeight = mHeight;
            this.mColor = mColor;
            this.style=style;

            init();
        }

        private void init() {
            mSpeed =  1;
            mDensity = 10;
            mIsFill = true;
            mIsAlpha = true;

            // 设置画笔样式
            mPaint = new Paint();
            mPaint.setColor(mColor);
            mPaint.setStrokeWidth(Util.dipToPX(context,1));
            if (mIsFill) {
                mPaint.setStyle(Paint.Style.FILL);
            } else {
                mPaint.setStyle(Paint.Style.STROKE);
            }
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setAntiAlias(true);

            // 添加第一个圆圈
            mRipples = new ArrayList<>();
            addNewCircle();

            mDensity = Util.dipToPX(context, mDensity);
        }

        private void addNewCircle(){
            Circle c = new Circle(0, 255);
            if(randColor)
                randomColorIfAble();
            c.color=color;
            mRipples.add(c);
        }

        /**
         * 圆到宽度
         *
         * @param canvas
         */
        private void drawInCircle(Canvas canvas) {
            canvas.save();

            // 处理每个圆的宽度和透明度
            for (int i = 0; i < mRipples.size(); i++) {
                Circle c = mRipples.get(i);
                mPaint.setColor(c.color);
                mPaint.setAlpha(c.alpha);// （透明）0~255（不透明）
                canvas.drawCircle(mWidth / 2, height / 2, c.width - mPaint.getStrokeWidth(), mPaint);

                // 当圆超出View的宽度后删除
                if (c.width > width / 2) {
                    mRipples.remove(i);
                } else {
                    // 计算不透明的数值，这里有个小知识，就是如果不加上double的话，255除以一个任意比它大的数都将是0
                    if (mIsAlpha) {
                        double alpha = 255 - c.width * (255 / ((double) mWidth / 2));
                        c.alpha = (int) alpha;
                    }
                    // 修改这个值控制速度
                    c.width += mSpeed;
                }
            }


            // 里面添加圆
            if (mRipples.size() > 0) {
                // 控制第二个圆出来的间距
                if (mRipples.get(mRipples.size() - 1).width > Util.dipToPX(context, mDensity)) {
                    addNewCircle();
                }
            }
            canvas.restore();
        }


        /**
         * 圆到对角线
         *
         * @param canvas
         */
        private void drawOutCircle(Canvas canvas) {
            canvas.save();

            // 使用勾股定律求得一个外切正方形中心点离角的距离
            sqrtNumber = (int) (Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2);

            // 变大
            for (int i = 0; i < mRipples.size(); i++) {
                // 启动圆圈
                Circle c = mRipples.get(i);
                mPaint.setColor(c.color);
                mPaint.setAlpha(c.alpha);// （透明）0~255（不透明）
                canvas.drawCircle(mWidth / 2, mHeight / 2, c.width - mPaint.getStrokeWidth(), mPaint);

                // 当圆超出对角线后删掉
                if (c.width > sqrtNumber) {
                    mRipples.remove(i);
                } else {
                    // 计算不透明的度数
                    double degree = 255 - c.width * (255 / (double) sqrtNumber);
                    c.alpha = (int) degree;
                    c.width += 1;
                }
            }

            // 里面添加圆
            //if (mRipples.size() > 0) {
                // 控制第二个圆出来的间距
                if (mRipples.get(mRipples.size() - 1).width == rand.nextInt(100)) {
                    addNewCircle();
                }
            //}
            canvas.restore();
        }

        private float breathDirection = 1;//呼吸方向（+1:变亮，-1:变暗）
        private float breathSpeed = 0.02f;//呼吸速度
        private boolean isBreathing = false;

        private int a = 0;
        private float breath = 1f;//控制呼吸
        private int waveCount = 5;//波纹的总个数

        public void drawBreath(Canvas canvas) {

            int alphaSpeed;
            float radiusSpeed;
            float hw = mWidth/2f;

            /**
             * 根据view的宽度计算半径和透明度的变化速度，（为了尽力保证半径和透明度同时达到最值：255是透明度的最大值）
             */
            if(hw >255f){
                radiusSpeed = hw/255f;
                alphaSpeed = 1;
            }else {
                alphaSpeed = new Float(255f/hw).intValue();
                radiusSpeed = 1;
            }

            /**
             * 控制呼吸
             */
            if(isBreathing){
                breath=breath+breathSpeed*breathDirection;
                if(breath>1 ){
                    breathDirection *= -1;//呼吸反向
                    if(beforBreathIsAwave){
                        isBreathing = false;
                        isStarting = true;
                        breath = 1;
                    }

                }else if(breath <0.001){
                    breathDirection *= -1;//呼吸反向
                    if(!beforBreathIsAwave){
                        isBreathing = false;
                        isStarting = false;
                        breath = 1;
                    }
                }
            }


            /**
             * 当达到设定的波距或第一次运行时 添加一个新波
             */
            if (++a>= (hw/waveCount) || mRipples.size()<1){
                a = 0;
                addNewCircle();
            }

            for (int i= 0;i< mRipples.size();i++){
                Circle temp = mRipples.get(i);
                if(isStarting){
                    temp.alpha=temp.alpha-alphaSpeed;//改变波的透明度
                    if(temp.alpha <0){
                        temp.alpha=0;
                    }
                    temp.width=temp.width + new Float(radiusSpeed).intValue();//增加波的半径
                }
                mPaint.setColor(temp.color);
                int tempAlpha = (int)(temp.alpha*breath);//乘以breath是为了通过改变透明度达到呼吸的效果
                mPaint.setAlpha(tempAlpha<0?0:tempAlpha);
                canvas.drawCircle(mWidth / 2, mHeight / 2, temp.width, mPaint);//绘制波


                /**
                 * 当波的半径大于本控件的宽大时删除这个波
                 */
                if( temp.width >mWidth || temp.alpha <0){
                    mRipples.remove(temp);
                }
            }
        }

        private boolean beforBreathIsAwave = true;
        private boolean isStarting = true;

        private int sleep=0;

        /**
         * 此方法调用一次波会呼吸一次
         */
        public synchronized void breath(){
            sleep++;
            if(sleep<10)
                return;
            sleep=0;
            this.beforBreathIsAwave =  isStarting;
            if(beforBreathIsAwave){
                breath = 1;
                breathDirection =-1;
            }
            else {
                breath = 0.01f;
                breathDirection = 1;
            }
            isBreathing = true;
        }

        @Override
        public void move(int maxWidth, int maxHight) {
            breath();
        }

        @Override
        public void onDraw(Canvas canvas, Paint mPaint) {
            switch (style){
                case BREATH:
                    //呼吸的
                    //drawBreath(canvas);
                    //break;
                case OUT:
                    // 外切正方形
                    drawOutCircle(canvas);
                    break;
                default:
                    // 内切正方形
                    drawInCircle(canvas);
            }
        }

        @Override
        public void setAnimatorEntryColor(int color) {

        }
    }


    class Circle {
        Circle(int width, int alpha) {
            this.width = width;
            this.alpha = alpha;
        }

        int width;

        int alpha;

        int color;
    }
}
